﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.IO;

using SvnAccess;

namespace Service {

    public class SvnService : ISvnService {

        /// <summary>
        /// Server Directory, where temporary files are stored
        /// </summary>
        private string TEMP_DIR = "D:\\Temp\\";

        /// <summary>
        /// Returns list of files in repository. (svn list)
        /// </summary>
        /// <param name="address">Repository address.</param>
        /// <param name="username">Username to svn repository.</param>
        /// <param name="password">Password to svn repository.</param>
        /// <returns>List of files and directories in string form.</returns>
        public string Svn_List(string address, string username, string password) {
            return Svn.List(address, username, password);
        }

        /// <summary>
        /// Save changes from your working copy on server side to the repository.
        /// </summary>
        /// <param name="from_where">Addrees from where will be changes saved.</param>
        /// <returns>True if commit is successfully completed, False otherwise.</returns>
        public bool Svn_Commit(string from_where) {
            return Svn.Commit(from_where);
        }

        /// <summary>
        /// Performs a recursive checkout from address_from to address_where on server.
        /// </summary>
        /// <param name="address_from">Repository address.</param>
        /// <param name="address_where">Destination address on server.</param>
        /// <param name="username">Username to svn repository.</param>
        /// <param name="password">Password to svn repository.</param>
        /// <returns>True if checkout is successfully completed, False otherwise.</returns>
        public bool Svn_Checkout(string address_from, string address_where, string username, string password) {
            return Svn.Checkout(address_from, address_where, username, password);
        }

        /// <summary>
        /// Returns content od file.
        /// </summary>
        /// <param name="svn_file_address">File address in svn repository.</param>
        /// <param name="username">Username to svn repository.</param>
        /// <param name="password">Password to svn repository.</param>
        /// <returns>File content, or ERROR message.</returns>
        public string Svn_LoadFile(string svn_file_address, string username, string password) {

            String SvnDirectoryPathToFile = svn_file_address.Substring(0, svn_file_address.LastIndexOf('/'));
            String TempUserDirectory = TEMP_DIR + username + "\\";
            
            Directory.CreateDirectory(TempUserDirectory);

            String TempLoadFileName = TEMP_DIR + svn_file_address.Substring(svn_file_address.LastIndexOf('/') + 1);
            String LoadFileText = "ERROR";

            try {
                Svn.Checkout(SvnDirectoryPathToFile, TempUserDirectory, username, password);
            }
            catch {
                LoadFileText = "ERROR: SVN CONNECT";
                goto CleanUp;
            }

            FileStream LoadFile;
            try {
                LoadFile = new FileStream(@TempLoadFileName, FileMode.Open);
            }
            catch {
                LoadFileText = "ERROR: FILE CANNOT BE FIND";
                goto CleanUp;
            }
            StreamReader Reader = new StreamReader(LoadFile);
            LoadFileText = Reader.ReadToEnd();
            Reader.Close();
            LoadFile.Close();

            CleanUp:
            DeleteDirectory(TempUserDirectory);

            return LoadFileText; 
        }

        /// <summary>
        /// Save new content of file (under subversion) to the repository.
        /// </summary>
        /// <param name="svn_file_address">File address in svn repository.</param>
        /// <param name="username">Username to svn repository.</param>
        /// <param name="password">Password to svn repository.</param>
        /// <param name="filetext">New content of selected file.</param>
        /// <returns>True if Svn_SaveFile is successfully completed, False otherwise.</returns>
        public bool Svn_SaveFile(string svn_file_address, string username, string password, string filetext) {

            String SvnDirectoryPathToFile = svn_file_address.Substring(0, svn_file_address.LastIndexOf('/'));
            String TempUserDirectory = TEMP_DIR + username + "\\";

            Directory.CreateDirectory(TempUserDirectory);

            String TempSaveFileName = TEMP_DIR + svn_file_address.Substring(svn_file_address.LastIndexOf('/') + 1);
            Boolean Result = true;

            try {
                Svn.Checkout(SvnDirectoryPathToFile, TempUserDirectory, username, password);
            }
            catch {
                Result = false;
                goto CleanUp;
            }

            FileStream SaveFile;
            try {
                SaveFile = new FileStream(@TempSaveFileName, FileMode.Truncate, FileAccess.Write);
            }
            catch {
                Result = false;
                goto CleanUp;
            }
            StreamWriter Writer = new StreamWriter(SaveFile);
            Writer.Write(filetext);
            Writer.Flush();
            Writer.Close();
            SaveFile.Close();

            try {
                Svn.Commit(TempUserDirectory);
            }
            catch {
                Result = false;
            }

        CleanUp:
            DeleteDirectory(TempUserDirectory);

            return Result;
        }

        /// <summary>
        /// Function deleted recursively a directory.
        /// </summary>
        /// <param name="target_dir">Directory that will be deleted.</param>
        private void DeleteDirectory(string target_dir) {
            string[] files = Directory.GetFiles(target_dir);
            string[] dirs = Directory.GetDirectories(target_dir);

            foreach (string file in files) {
                File.SetAttributes(file, FileAttributes.Normal);
                File.Delete(file);
            }

            foreach (string dir in dirs) {
                DeleteDirectory(dir);
            }

            Directory.Delete(target_dir, false);
        }

    }
}
